package cn.colins.raft.rpc;

import cn.colins.raft.ResourceLifeCycle;
import cn.colins.raft.config.ServerConfig;
import cn.colins.raft.exception.RaftException;
import cn.colins.raft.exception.RaftRunException;
import cn.colins.raft.rpc.handler.RpcClientHandlerInit;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.CountDownLatch;


/**
 * @Description
 * @Author czl
 * @Version V1.0.0
 * @Since 1.0
 * @Date 2023/6/12
 */
public class RpcClient implements Runnable, ResourceLifeCycle {

    private final static Logger log = LoggerFactory.getLogger(RpcClient.class);

    private EventLoopGroup group = null;

    private ChannelInitializer channelInitializer;

    private ServerConfig serverConfig;
    private ChannelFuture future;

    private boolean connectStatus=false;

    private CountDownLatch countDownLatch=new CountDownLatch(1);


    public RpcClient(ServerConfig serverConfig) {
        this.serverConfig = serverConfig;
        this.channelInitializer = new RpcClientHandlerInit();
        this.group = new NioEventLoopGroup();
        this.connect();
    }

    private ChannelFuture connect() {
        Bootstrap bootstrap = new Bootstrap();
        // 客户端不需要处理连接 所以一个线程组就够了
        bootstrap.group(group)
                // 连接通道
                .channel(NioSocketChannel.class)
                .remoteAddress(serverConfig.getAddress(), serverConfig.getPort())
                .option(ChannelOption.TCP_NODELAY, true)
                // 数据处理
                .handler(channelInitializer);

        future = bootstrap.connect();
        future.addListener(event -> {
            if (event.isSuccess()) {
                log.info("连接Server 成功,地址：{},端口：{}", serverConfig.getAddress(), serverConfig.getPort());
                connectStatus=true;
                countDownLatch.countDown();
            }else {
                log.info("连接Server 失败,地址：{},端口：{}", serverConfig.getAddress(), serverConfig.getPort());
                countDownLatch.countDown();
            }
        });
        return future;
    }

    public boolean getConnectStatus(){
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return this.connectStatus;
    }

    public Channel getChannelFuture(){
        return future.channel();
    }


    @Override
    public void init() {
        try {
            future.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            log.error("Client start error：{},{}", e.getMessage(), e);
        } finally {
            destroy();
        }
    }

    @Override
    public void destroy() {
        // 优雅的关闭 释放资源
        if (group != null) {
            group.shutdownGracefully();
        }
    }

    @Override
    public void run() {
        init();
    }

}
